package com.syg.rabbitmq.producer;


import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 发布订阅模式需要声明fanout交换机
 * <br/>
 * <br/>
 * fanout类型的交换机不需要声明routingKey,会发送到所有的队列
 * <br/>
 * <br/>
 *
 * <img width="957px" height="455px" src="../../../../../resources/picture/发布订阅模式.png" alt="发布订阅模式需要声明fanout交换机">
 *     <br/>
 *     和上面2种模式默认提供的交换机不同的是，该模式需要显示声明交换机，
 *     然后创建多个队列和这个交换机绑定。
 *     生产者发送消费给mq时需要指定交换机，然后交换机将消息转发给与自己绑定的所有队列。
 *     消费者监听指定的队列获得消息，每个队列可以有多个消费者监听，同样也是轮询的机制发送给消费者
 */
public class Publish_Subscribe_Producer {

    public static void main(String[] args) throws IOException, TimeoutException {

        // 1,创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        //2,设置参数
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 3,创建连接
        Connection connection = factory.newConnection();
        // 4,创建Channel
        Channel channel = connection.createChannel();

        /*
        * exchangeDeclare(String exchange,BuiltinExchangeType type,boolean durable,boolean autoDelete,boolean internal,Map<String, Object> arguments)
        * 参数：
        *   exchange：交换机
        *   type：交换机类型
        *   durable:持久化
        *   autoDelete：自动删除
        *   internal：mq内部使用,一般false
        *   arguments：参数
        * */
        // 5,创建交换机
        String exchangeName = "test_fanout";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT, true, false, false, null);

        // 6,创建队列
        String queueFanout1 = "queueFanout1";
        String queueFanout2 = "queueFanout2";
        channel.queueDeclare(queueFanout1, true, false, false, null);
        channel.queueDeclare(queueFanout2, true, false, false, null);

        /*
        * fanout类型的交换机不需要声明routingKey,会发送到所有的队列
        * */
        // 7,绑定队列和交换机
        channel.queueBind(queueFanout1, exchangeName, "");
        channel.queueBind(queueFanout2, exchangeName, "");

        // ------执行以上代码,管理台会看到队列与交换机-----------

        // 8,发送消息(fanout不需要声明路由key)
        String content = "fanout类型的交换机——发布订阅模式";
        channel.basicPublish(exchangeName, "", null, content.getBytes());

        // 9,释放资源
    }
}
